#ifndef INPUTGEOM_H
#define INPUTGEOM_H

#include "ChunkyTriMesh.h"
#include "MeshLoader.h"

static const int MAX_CONVEXVOL_PTS = 12;
struct ConvexVolume
{
	fixed64 verts[MAX_CONVEXVOL_PTS*3];
	fixed64 hmin, hmax;
	int nverts;
	int area;
};

struct BuildSettings
{
	// Cell size in world units
	fixed64 cellSize;
	// Cell height in world units
	fixed64 cellHeight;
	// Agent height in world units
	fixed64 agentHeight;
	// Agent radius in world units
	fixed64 agentRadius;
	// Agent max climb in world units
	fixed64 agentMaxClimb;
	// Agent max slope in degrees
	fixed64 agentMaxSlope;
	// Region minimum size in voxels.
	// regionMinSize = sqrt(regionMinArea)
	fixed64 regionMinSize;
	// Region merge size in voxels.
	// regionMergeSize = sqrt(regionMergeArea)
	fixed64 regionMergeSize;
	// Edge max length in world units
	fixed64 edgeMaxLen;
	// Edge max error in voxels
	fixed64 edgeMaxError;
	fixed64 vertsPerPoly;
	// Detail sample distance in voxels
	fixed64 detailSampleDist;
	// Detail sample max error in voxel heights.
	fixed64 detailSampleMaxError;
	// Partition type, see SamplePartitionType
	int partitionType;
	// Bounds of the area to mesh
	fixed64 navMeshBMin[3];
	fixed64 navMeshBMax[3];
	// Size of the tiles in voxels
	fixed64 tileSize;
};

class InputGeom
{
	rcChunkyTriMesh* m_chunkyMesh;
	rcMeshLoaderObj* m_mesh;
	fixed64 m_meshBMin[3], m_meshBMax[3];
	BuildSettings m_buildSettings;
	bool m_hasBuildSettings;
	
	/// @name Off-Mesh connections.
	///@{
	static const int MAX_OFFMESH_CONNECTIONS = 256;
	fixed64 m_offMeshConVerts[MAX_OFFMESH_CONNECTIONS*3*2];
	fixed64 m_offMeshConRads[MAX_OFFMESH_CONNECTIONS];
	unsigned char m_offMeshConDirs[MAX_OFFMESH_CONNECTIONS];
	unsigned char m_offMeshConAreas[MAX_OFFMESH_CONNECTIONS];
	unsigned short m_offMeshConFlags[MAX_OFFMESH_CONNECTIONS];
	unsigned int m_offMeshConId[MAX_OFFMESH_CONNECTIONS];
	int m_offMeshConCount;
	///@}

	/// @name Convex Volumes.
	///@{
	static const int MAX_VOLUMES = 256;
	ConvexVolume m_volumes[MAX_VOLUMES];
	int m_volumeCount;
	///@}
	
public:
	InputGeom();
	~InputGeom();
	
	bool loadMesh(const std::string& filepath);
	bool loadMesh(unsigned char* buf, int length);
	bool loadGeomSet(const std::string& filepath);
	bool loadGeomSet(unsigned char* buf, int length);
	
	/// Method to return static mesh data.
	const rcMeshLoaderObj* getMesh() const { return m_mesh; }
	const fixed64* getMeshBoundsMin() const { return m_meshBMin; }
	const fixed64* getMeshBoundsMax() const { return m_meshBMax; }
	const fixed64* getNavMeshBoundsMin() const { return m_hasBuildSettings ? m_buildSettings.navMeshBMin : m_meshBMin; }
	const fixed64* getNavMeshBoundsMax() const { return m_hasBuildSettings ? m_buildSettings.navMeshBMax : m_meshBMax; }
	const rcChunkyTriMesh* getChunkyMesh() const { return m_chunkyMesh; }
	const BuildSettings* getBuildSettings() const { return m_hasBuildSettings ? &m_buildSettings : 0; }
	bool raycastMesh(fixed64* src, fixed64* dst, fixed64& tmin);

	/// @name Off-Mesh connections.
	///@{
	int getOffMeshConnectionCount() const { return m_offMeshConCount; }
	const fixed64* getOffMeshConnectionVerts() const { return m_offMeshConVerts; }
	const fixed64* getOffMeshConnectionRads() const { return m_offMeshConRads; }
	const unsigned char* getOffMeshConnectionDirs() const { return m_offMeshConDirs; }
	const unsigned char* getOffMeshConnectionAreas() const { return m_offMeshConAreas; }
	const unsigned short* getOffMeshConnectionFlags() const { return m_offMeshConFlags; }
	const unsigned int* getOffMeshConnectionId() const { return m_offMeshConId; }
	void addOffMeshConnection(const fixed64* spos, const fixed64* epos, const fixed64 rad,
							  unsigned char bidir, unsigned char area, unsigned short flags);
	void deleteOffMeshConnection(int i);
	///@}

	/// @name Box Volumes.
	///@{
	int getConvexVolumeCount() const { return m_volumeCount; }
	const ConvexVolume* getConvexVolumes() const { return m_volumes; }
	void addConvexVolume(const fixed64* verts, const int nverts,
						 const fixed64 minh, const fixed64 maxh, unsigned char area);
	void deleteConvexVolume(int i);
	///@}
	
private:
	// Explicitly disabled copy constructor and copy assignment operator.
	InputGeom(const InputGeom&);
	InputGeom& operator=(const InputGeom&);
};

#endif // INPUTGEOM_H
